/*
 * Copyright 2010 - Jeremie Brebec
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.jb.sharedbills.client.form;

import java.util.ArrayList;
import java.util.List;

import org.jb.sharedbills.client.resources.Resources;
import org.jb.sharedbills.client.stores.EventSaver;
import org.jb.sharedbills.client.stores.GroupStore;
import org.jb.sharedbills.client.stores.EventSaver.SaveStateListener;
import org.jb.sharedbills.client.stores.EventSaver.State;
import org.jb.sharedbills.shared.model.Group;
import org.jb.sharedbills.shared.model.MessageHelper;
import org.jb.sharedbills.shared.model.logic.EventConstraints;

import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.store.StoreFilter;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Dialog;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.grid.CellEditor;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.grid.GridSelectionModel;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Anchor;
import com.google.inject.Inject;

public class GroupPanel extends ContentPanel implements SaveStateListener {

	/**
	 * 
	 * @param members
	 */
	@Inject
	public GroupPanel( GroupStore store, EventSaver eventSaver ) {
		
		this.groupStore = store;
		this.eventSaver = eventSaver;
		
		setHeaderVisible(false);
		setBorders(false);
		setLayout( new FitLayout() );
		
		setTopComponent( createToolbar() );

		eventSaver.addListener(this);
		
		add( createGrid() );
		
	}
	
	/**
	 * 
	 * @return
	 */
	private Grid<BeanModel> createGrid() {
		
		groupStore.addFilter( new StoreFilter<BeanModel>() {
			
			@Override
			public boolean select(Store<BeanModel> store, BeanModel parent, BeanModel item, String property) {
				return item.<Group>getBean().getKind() == Group.Kind.CUSTOM;
			}
		});
		groupStore.applyFilters("kind");
		
		List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
		ColumnConfig columnName = new ColumnConfig("name","Nom",50);
		TextField<String> text = new TextField<String>();  
	    text.setAllowBlank(false);  
	    columnName.setEditor(new CellEditor(text)); 
	    
		ColumnConfig columnMember = new ColumnConfig("members", "Membres", 200);
		columnMember.setRenderer( new GridCellRenderer<BeanModel>() {

			@Override
			public Object render(final BeanModel model, String property,
					ColumnData config, int rowIndex, int colIndex,
					ListStore<BeanModel> store, Grid<BeanModel> grid) {
				
				Anchor anchor = new Anchor( MessageHelper.format( model.<Group>getBean().getMembers() ) );
				anchor.addClickHandler( new ClickHandler() {

					@Override
					public void onClick(ClickEvent event) {
						GroupDialog dlg = new GroupDialog(groupStore.getEvent(), model.<Group>getBean() );
						if (eventSaver.getState() == State.LOCKED)
							dlg.disableEdit();
						dlg.show();
					}
				} );
				
				return anchor;
			}
		});
		columns.add(columnName);
		columns.add(columnMember);
		ColumnModel cm = new ColumnModel(columns);

		grid = new EditorGrid<BeanModel>(groupStore,cm);
		grid.setSelectionModel( new GridSelectionModel<BeanModel>() );
		grid.setAutoExpandColumn("name");
		
		grid.addListener(Events.BeforeEdit, new Listener<GridEvent<BeanModel>>() {
			@Override
			public void handleEvent(GridEvent<BeanModel> be) {
				if (eventSaver.getState() == State.LOCKED) {
					be.setCancelled(true);
				}
			}
		});
		
		return grid;
	}
	
	/**
	 * 
	 * @return
	 */
	private ToolBar createToolbar() {
		ToolBar tb = new ToolBar();
		
		addBtn = new Button("Créer", AbstractImagePrototype.create(Resources.INSTANCE.add()));
		addBtn.addSelectionListener( new SelectionListener<ButtonEvent>() {
			
			@Override
			public void componentSelected(ButtonEvent ce) {
				
				GroupDialog dialog = new GroupDialog( groupStore.getEvent(), (Group)null );
				dialog.show();
				
			}
		});
		addBtn.disable();
		tb.add( addBtn );
		deleteBtn = new Button("Supprimer", AbstractImagePrototype.create(Resources.INSTANCE.delete()));
		deleteBtn.disable();
		deleteBtn.addSelectionListener( new SelectionListener<ButtonEvent>() {

			@Override
			public void componentSelected(ButtonEvent ce) {
				BeanModel m = grid.getSelectionModel().getSelectedItem();
				if (m == null) {
					MessageBox dlg = MessageBox.alert("Suppression", "Aucune ligne sélectionnée" , new Listener<MessageBoxEvent>() {
						@Override
						public void handleEvent(MessageBoxEvent be) {}
					});
					dlg.show();
					return;
				}

				final Group group = m.getBean();
				if (!EventConstraints.checkGroupDeletion(groupStore.getEvent(), group)) {
					StringBuilder b = new StringBuilder();
					b.append( "Impossible de supprimer le groupe <i>" );
					b.append( group.getName() );
					b.append( "</i><br>Vérifiez qu'aucune dépense n'a été payé pour ce groupe.");
					MessageBox dlg = MessageBox.alert("Suppression", b.toString() , new Listener<MessageBoxEvent>() {
						@Override
						public void handleEvent(MessageBoxEvent be) {}
					});
					dlg.setIcon(MessageBox.ERROR);
					dlg.show();
					dlg.getDialog().setWidth( 400 );
					return;
				}
				
				MessageBox dlg = MessageBox.confirm("Suppression", "Voulez-vous vraiment supprimer ce groupe ?", new Listener<MessageBoxEvent>() {

					@Override
					public void handleEvent(MessageBoxEvent be) {
						if (Dialog.YES.equals( be.getButtonClicked().getItemId())) {
							groupStore.getEvent().getGroups().remove( group );
						}
					}
				});
				dlg.show();	
			}
		});
		tb.add( deleteBtn );
		
		return tb;
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.jb.sharedbills.client.stores.EventSaver.SaveStateListener#onStateChange(org.jb.sharedbills.client.stores.EventSaver.State)
	 */
	@Override
	public void onStateChange(State state) {
		if (state == State.COMMIT) {
			groupStore.commitChanges();
		}
		
		if (state != State.LOCKED) {
			addBtn.enable();
			deleteBtn.enable();
		}
	}
	
	private EditorGrid<BeanModel> grid;
	
	private GroupStore groupStore;

	private final EventSaver eventSaver;

	private Button addBtn;
	private Button deleteBtn;

}
